/**
 * @file    udp_server.c
 * @brief   测试两个Linux主机（一个客户端，一个服务器）通过UDP协议通信
 * @author  zyh <2972140442@qq.com>
 * @date    2025-06-26
 * @license GPL-2.0
 * @note    服务器负责接收数据并显示在终端，本文件为服务器
 */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

// 调试用错误输出宏
#define LOG_ERROR(fmt, ...) \
    fprintf(stderr, "[ERROR] %s:%d (%s): " fmt "\n", \
            __FILE__, __LINE__, __func__, ##__VA_ARGS__)


int main()
{
    // UDP协议使用下面的数据类型来存储 目标IP 和 目标端口
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(8081);

    char rev_buf[512];
    // 创建UDP套接字文件
    int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if ( -1 == udp_socket )
    {
        LOG_ERROR("semget failed,error: %d, %s\n", errno, strerror(errno));
        exit(errno);
    }

    // 绑定地址和端口
    if ( -1 == bind(udp_socket, (const struct sockaddr *)&server_addr, sizeof(server_addr)) )
    {
        LOG_ERROR("semget failed,error: %d, %s\n", errno, strerror(errno));
        exit(errno);        
    }
    // 接收数据
    memset(rev_buf, 0, sizeof(rev_buf));
    if ( -1 == recvfrom(udp_socket, rev_buf, sizeof(rev_buf), 0,
                 NULL, NULL) )
    {
        LOG_ERROR("semget failed,error: %d, %s\n", errno, strerror(errno));
        exit(errno);        
    }

    printf("%s\n",rev_buf);

    if ( -1 == close(udp_socket) )
    {
        LOG_ERROR("semget failed,error: %d, %s\n", errno, strerror(errno));
        exit(errno);       
    }


    return 0;
}